# backend/crud/user_subscription.py
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from backend.models.user_subscription import UserSubscription
from backend.schemas.user_subscription import UserSubscriptionCreate
from typing import List


async def create_user_subscription(db: AsyncSession, data: UserSubscriptionCreate):
    us = UserSubscription(**data.dict())
    db.add(us)
    await db.commit()
    await db.refresh(us)
    return us


async def get_user_subscriptions(db: AsyncSession, user_id: str):
    result = await db.execute(
        select(UserSubscription).where(UserSubscription.user_id == user_id)
    )
    return result.scalars().all()


async def get_user_subscriptions_by_id(db: AsyncSession, user_subscription_id: str):
    """根据订阅ID获取用户订阅"""
    result = await db.execute(
        select(UserSubscription).where(UserSubscription.id == user_subscription_id)
    )
    return result.scalars().all()


async def get_used_ips(db: AsyncSession, node_id: str) -> List[str]:
    """获取节点已使用的IP地址列表"""
    result = await db.execute(
        select(UserSubscription.client_ip).where(
            UserSubscription.node_id == node_id,
            UserSubscription.client_ip.isnot(None)
        )
    )
    return [ip for ip in result.scalars().all() if ip]


async def update_wireguard_info(
        db: AsyncSession,
        user_subscription_id: str,
        private_key: str,
        public_key: str,
        client_ip: str
):
    """更新用户订阅的WireGuard信息"""
    result = await db.execute(
        select(UserSubscription).where(UserSubscription.id == user_subscription_id)
    )
    user_sub = result.scalar_one_or_none()

    if user_sub:
        user_sub.wg_private_key = private_key
        user_sub.wg_public_key = public_key
        user_sub.client_ip = client_ip
        await db.commit()
        await db.refresh(user_sub)

    return user_sub


# backend/crud/user_subscription.py - 确保函数存在

async def switch_user_subscription_node(
        db: AsyncSession,
        user_subscription_id: str,
        new_node_id: str
):
    """
    切换用户订阅的节点
    """
    try:
        print(f"🔍 CRUD调试 - 开始节点切换:")
        print(f"   用户订阅ID: {user_subscription_id}")
        print(f"   新节点ID: {new_node_id}")

        # 获取用户订阅
        result = await db.execute(
            select(UserSubscription).where(UserSubscription.id == user_subscription_id)
        )
        user_sub = result.scalar_one_or_none()

        if not user_sub:
            print("❌ 用户订阅不存在")
            return None, "用户订阅不存在"

        print(f"✅ 找到用户订阅: {user_sub.id}")

        # 检查新节点是否存在
        from backend.crud.node import get_node
        new_node = await get_node(db, new_node_id)
        if not new_node:
            print("❌ 新节点不存在")
            return None, "新节点不存在"

        print(f"✅ 找到新节点: {new_node.name} ({new_node.id})")

        # 检查新节点是否激活
        if not new_node.is_active:
            print("❌ 新节点未激活")
            return None, "新节点未激活"

        # 保存旧节点ID（用于回滚）
        old_node_id = user_sub.node_id
        old_client_ip = user_sub.client_ip

        print(f"📝 从节点 {old_node_id} 切换到 {new_node_id}")
        print(f"📝 旧IP: {old_client_ip}")

        # 更新节点ID
        user_sub.node_id = new_node_id

        # 获取新节点已使用的IP列表
        used_ips = await get_used_ips(db, new_node_id)
        print(f"📊 新节点已使用IP: {used_ips}")

        # 为新节点分配IP地址
        from backend.core.wireguard import WireGuardManager
        wg_manager = WireGuardManager()

        try:
            new_client_ip = wg_manager.allocate_client_ip(new_node.subnet, used_ips)
            user_sub.client_ip = new_client_ip
            print(f"✅ 分配新IP: {new_client_ip}")
        except ValueError as e:
            # 如果IP分配失败，回滚节点切换
            user_sub.node_id = old_node_id
            user_sub.client_ip = old_client_ip
            print(f"❌ IP分配失败: {str(e)}")
            return None, f"IP地址分配失败: {str(e)}"

        # 提交更改
        await db.commit()
        await db.refresh(user_sub)

        print("✅ 节点切换成功完成")
        return user_sub, "节点切换成功"

    except Exception as e:
        await db.rollback()
        print(f"❌ 节点切换异常: {str(e)}")
        import traceback
        print(f"🔍 异常详情: {traceback.format_exc()}")
        return None, f"节点切换失败: {str(e)}"


async def can_switch_node(db: AsyncSession, user_subscription_id: str) -> bool:
    """
    检查用户订阅是否可以切换节点
    """
    result = await db.execute(
        select(UserSubscription).where(UserSubscription.id == user_subscription_id)
    )
    user_sub = result.scalar_one_or_none()

    if not user_sub:
        return False

    # 检查订阅是否激活
    if not user_sub.is_active:
        return False

    # 检查订阅是否过期
    from datetime import datetime
    if user_sub.expires_at < datetime.utcnow():
        return False

    return True